package org.example.platform.elasticsearch.service;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.example.platform.elasticsearch.dao.CommonDao;
import org.example.platform.elasticsearch.entity.CommonInfo;
import org.example.platform.elasticsearch.entity.Hotel;
import org.example.platform.elasticsearch.entity.HotelDocRequest;
import org.example.platform.elasticsearch.entity.Location;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.Method;
import java.util.*;

@Service
@Slf4j
public class ESQueryCommonService {
    @Autowired
    private RestHighLevelClient client;
    @Autowired
    CommonService commonService;
    @Autowired
    ESQueryDocService eSQueryDocService;
    @Autowired
    CommonDao commonDao;



    /**
     * 查询所有文档
     *
     * @param searchRequest
     * @return
     */
    public List<Hotel> getQueryResult(SearchRequest searchRequest) throws Exception {
        ArrayList<Hotel> list = new ArrayList<>();
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        RestStatus status = searchResponse.status();
        if (status != RestStatus.OK) {
            return Collections.emptyList();
        }
        SearchHits searchHits = searchResponse.getHits();
        for (SearchHit searchHit : searchHits) {
            Hotel h = new Hotel();
            h.setId(searchHit.getId());
            h.setIndex(searchHit.getIndex());   //索引名称
            h.setScore(searchHit.getScore());   //文档得分
            Map<String, Object> dataMap = searchHit.getSourceAsMap();
            h.setTitle((String) dataMap.get("title"));
            h.setCity((String) dataMap.get("city"));
            String price = (String) dataMap.get("price");
            if (StrUtil.isNotBlank(price)) {
                h.setPrice(Double.valueOf(price));
            }

            Object location = (String) dataMap.get("location");
            if (null != location) {
                h.setLocation(JSONUtil.toBean(JSONUtil.toJsonStr(location), Location.class));
            }
            list.add(h);
        }

        return list;
    }


    /**
     * 查询
     *
     * @param hotelDocRequest
     * @return
     * @throws Exception
     */
    public List<Hotel> query(HotelDocRequest hotelDocRequest) throws Exception {
        String indexName = hotelDocRequest.getIndexName();
        commonService.indexNameIsBlank(indexName);
        // 新建搜索请求
        SearchRequest searchRequest = new SearchRequest(indexName);
        // 分流找对应的方法
        SearchSourceBuilder searchSourceBuilder = this.queryType(hotelDocRequest);
        searchRequest.source(searchSourceBuilder);
        return this.getQueryResult(searchRequest);
    }

    /**
     * 分流查询不同类型查询方法
     *
     * @return
     */
    public SearchSourceBuilder queryType(HotelDocRequest hotelDocRequest) throws Exception {
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//        List<CommonInfo>  list = commonDao.queryCommonInfo();
//        if(!list.isEmpty()){
//            for (int i=0;i<list.size();i++){
//                if(hotelDocRequest.getType().equals(list.get(i).getType())){
//                    Class clas = Class.forName(list.get(i).getClassName());
//                    Object o = clas.newInstance();
//                    Method method = clas.getMethod(list.get(i).getMethod(),HotelDocRequest.class, SearchSourceBuilder.class);
//                    searchSourceBuilder = (SearchSourceBuilder) method.invoke(o,hotelDocRequest,searchSourceBuilder);
//                }
//            }
//        }



        switch (hotelDocRequest.getType()) {
            case "must_not":
                searchSourceBuilder = eSQueryDocService.mustNotQuery(searchSourceBuilder);
                break;
            case "should":
                searchSourceBuilder = eSQueryDocService.shouldQuery(searchSourceBuilder);
                break;
            case "must":
                searchSourceBuilder = eSQueryDocService.mustQuery(hotelDocRequest, searchSourceBuilder);
                break;
            case "exist":
                searchSourceBuilder = eSQueryDocService.existQuery(hotelDocRequest, searchSourceBuilder);
                break;
            case "range":
                searchSourceBuilder = eSQueryDocService.rangeQuery(hotelDocRequest, searchSourceBuilder);
                break;
            case "terms":
                searchSourceBuilder = eSQueryDocService.termsQuery(hotelDocRequest, searchSourceBuilder);
                break;
            case "filter":
                searchSourceBuilder = eSQueryDocService.filterQuery(searchSourceBuilder);
                break;
            case "getCityByCreateTime":
                searchSourceBuilder = eSQueryDocService.getCityByCreateTime(hotelDocRequest, searchSourceBuilder);
                break;
            case "constantScore":
                searchSourceBuilder = eSQueryDocService.constantScore(searchSourceBuilder);
                break;
            case "functionScoreScore":
                searchSourceBuilder = eSQueryDocService.functionScoreScore(hotelDocRequest, searchSourceBuilder);
                break;
            case "geoBoundingBoxQuery":
                searchSourceBuilder = eSQueryDocService.geoBoundingBoxQuery( searchSourceBuilder);
                break;
            case "geoDistanceQuery":
                searchSourceBuilder = eSQueryDocService.geoDistanceQuery(searchSourceBuilder);
                break;
            case "geoPolygonQuery":
                searchSourceBuilder = eSQueryDocService.geoPolygonQuery(searchSourceBuilder);
                break;

            default:
        }

        return searchSourceBuilder;
    }


}
